﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

#pragma once
#include "GcmpModelInterface.h"
#include "IObject.h"
#include <string>
#include <vector>
#include <future>
#include "GcmpApiDeclaration.h"

namespace gcmp
{
    class IDocument;
    class IDatasetVersion;
    class ICollaborationProjectConfiguration;
    class IElementCloudStandardContentPublisher;
    enum class CollaborationProjectConfigurationType;

    /// \brief MvdOption用来按照数据类型分步存储工作单元
    ///
    /// Ref: brep + parameters 数据
    /// View: mesh + parameters 数据
    /// Std: brep + mesh + parameters 数据
    /// Raw: blob 数据
    /// All: 全数据
    enum class GCMP_MODEL_INTERFACE_EXPORT MvdOption : int32_t
    {
        Ref,
        View,
        Std,
        Raw,
        All
    };

    enum class GCMP_MODEL_INTERFACE_EXPORT ReservedSubIdType : int32_t
    {
        CreateLinkDocument,
        CreateTemplateDocument,
    };

    enum class GCMP_MODEL_INTERFACE_EXPORT AutoSaveErrorType : int32_t
    {
        NothingModified = 1,            // fail, 无改动 
        TranslateFail = 2,              // fail, 转换失败
        InGroupTransaction = 3,         // fail, 在事务组中
        IsSyncingLocalCache = 4,        // fail, 正在写缓存
        InElcEnv = 5,                   // fail, 在构件级协同环境
        AutoSaveDisabled = 6,           // fail, 自动缓存未开启
        IsSchemaChanged = 7,            // fail, 有数据版本变更
        DisableByTransactionEvent = 8   // fail, 事务提交缓存功能关闭
    };

    /// \brief 工作单元推送参数
    struct DatasetPushParams
    {
        DatasetPushParams(IElementCloudStandardContentPublisher* publisher, MvdOption mvd, int targetVersion, std::string& errorCodeJson)
            : Publisher(publisher)
            , Mvd(mvd)
            , TargetVersion(targetVersion)
            , ErrorCodeJson(errorCodeJson)
        {}

        IElementCloudStandardContentPublisher * Publisher = nullptr;                                    /// < [in]对象云端BIM标准数据产生器
        MvdOption Mvd = MvdOption::All;                                                                 /// < [in]数据类型
        int StartVersionForUploadStandard = -1;                                                         /// < [in]标准数据转换相关，非-1表示有效值；当为有效值时，用于指定版本StartVersionForUploadStandard 到 targetVersion之间的增量数据转换；
        int TargetVersion = -1;                                                                         /// < [in]目标版本。-1表示最新
        std::wstring Comment;                                                                           /// < [in]评论
        bool IsElcEnabled = false;                                                                      /// < [in]未启用。是否使用ElC
        bool ToRemote = true;                                                                           /// < [in]推送到远端-true；推送到本地-false
        bool ExportFullContentData = false;                                                             /// < [in]是否导出全量数据
        std::function<void(int percentage, const std::wstring& info)> ReportProgressCallback = nullptr; /// < [in]导出云端工作单元到本地时，进行进度汇报回调(暂时只支持导出进度汇报)
        std::string DamagedJobId;                                                                       /// < [in]损坏的工作单元job id
        std::string TxId;                                                                               /// < [in]全局事务 id
        std::string ReplacementDatasetId;                                                               /// < [In]替换工作单元 id
        std::string& ErrorCodeJson;                                                                     /// < [out]结果字符串，JSON格式。调用者传入
        std::wstring* ResultLocalFileFullPath = nullptr;                                                /// < [out]当选择推送到本地时，生成的数据压缩包本地路径。调用者传入
        bool IsSupportZeroElementCommit = false;                                                        /// < [out]设置是否支持无修改提交
    };

    /// \brief 数据集接口
    ///
    /// 提供数据集的创建以及操作接口
    class GCMP_MODEL_INTERFACE_EXPORT IDataset : public IObject
    {
        DEFINE_CAST_DERIVED(gcmp::IDataset, gcmp::IObject)

    public:

        /// \brief 根据类型获取前100个预留subId
        /// \return eType 类型
        static int GetReservedSubId(ReservedSubIdType eType);

        /// \brief 获取数据集Id。在创建时确定，是全球唯一的。
        /// \return std::wstring 数据集Id
        virtual std::wstring GetId() const = 0;

        /// \brief 获取数据集Sub-Id
        /// \return int for sub-id
        virtual int GetSubId() const = 0;

        /// \brief 获取数据集名字
        /// \return std::wstring 数据集名字
        virtual std::wstring GetName() const = 0;

        /// \brief 设置user session id
        /// \return 
        virtual void SetSessionId(const std::string& sessionId) = 0;


        /// \brief 获取数据集关联的文档
        ///
        /// 创建或者加载数据集之后，可以获取和此数据集关联的文档。
        /// 修改数据集，需要通过此文档指针。
        /// \return IDocument * 文档c    
        virtual IDocument * GetDocument() const = 0;

        /// \brief 设置文档，设置后会将原文档覆盖
        /// \return 成功返回true
        virtual bool SetDocument(IDocument* pDocument) = 0;

        /// \brief 保存修改，不生成新版本。
        ///
        /// 通过关联的文档进行修改，可以多次保存
        /// \param [out] AutoSaveErrorType AutoSave具体错误信息
        /// \return bool 是否保存成功
        /// \see GetDocument()
        virtual bool Save(AutoSaveErrorType& errorType) = 0;
        virtual bool Save(std::string& strErrorCodeJson, const bool bIsElcEnabled, AutoSaveErrorType& errorType) = 0;

        /// \ brief 将工作单元仅保存到本地，不会产生新的版本，不会上传至云端
        ///
        /// 发布的是BIM标准数据，供协作用。
        /// \param pElementCloudStandardContentPublisher 提供对象的标准数据内容，传入nullptr则不发布对象的任何内容。
        ///     目前实现时传入nullptr，则发布预定义的标准数据，可能不是想要的、或者是不够的。
        /// return true保存成功 ，false保存失败
        virtual bool SaveToLocal(IElementCloudStandardContentPublisher * pElementCloudStandardContentPublisher) = 0;
        virtual bool SaveToLocal(IElementCloudStandardContentPublisher * pElementCloudStandardContentPublisher, std::string& strErrorCodeJson, const bool bIsElcEnabled) = 0;

#pragma region 版本
        /// \brief 获取当前版本
        /// \return const IDatasetVersion* 当前版本
        virtual const IDatasetVersion* GetCurrentVersion() const = 0;

        /// \brief 获取最新版本
        /// \return OwnerPtr<IDatasetVersion> 最新版本
        GCMP_OBSOLETE_API(2021 / 12 / 30, GetLatestVersion(std::string& strErrorCodeJson) const)
        virtual OwnerPtr<IDatasetVersion> GetLatestVersion() const = 0;
        virtual OwnerPtr<IDatasetVersion> GetLatestVersion(std::string& strErrorCodeJson) const = 0;

        /// \brief 查询所有版本
        /// \return std::vector<OwnerPtr<IDatasetVersion>> 所有版本
        virtual std::vector<OwnerPtr<IDatasetVersion>> QueryAllVersions() const = 0;
#pragma endregion

        /// \brief 根据协同工程配置类型获得协同工程配置
        /// \param configurationType 协同工程配置类型
        /// \return 协同工程配置
        virtual ICollaborationProjectConfiguration* GetProjectConfiguration(CollaborationProjectConfigurationType configurationType) = 0;

        /// \brief 根据协同工程配置类型获得协同工程配置
        /// \param configurationType 协同工程配置类型
        /// \return 协同工程配置
        virtual const ICollaborationProjectConfiguration* GetProjectConfiguration(CollaborationProjectConfigurationType configurationType) const = 0;

        /// \brief 根据协同工程配置类型获得协同工程配置
        /// \param arrProjectConfigs 协同工程配置
        /// \param configurationType 协同工程配置类型
        /// \return 返回是否获取成功
        virtual bool GetProjectConfigs(std::vector<const ICollaborationProjectConfiguration*>& arrProjectConfigs, CollaborationProjectConfigurationType configurationType) const = 0;

        /// \brief 根据协同工程配置类型获得协同工程配置
        /// \param arrProjectConfigs 协同工程配置
        /// \param configurationType 协同工程配置类型
        /// \return 返回是否获取成功
        virtual bool GetProjectConfigs(std::vector<ICollaborationProjectConfiguration*>& arrProjectConfigs, CollaborationProjectConfigurationType configurationType) = 0;

        /// \brief 追加创建协同工程项目配置项
        /// \param configType 配置类型
        /// \param buildingItemId 子项id
        /// \param configId 配置项id
        /// \param version 配置项版本
        /// \return 返回是否添加成功
        virtual bool AppendProjectItemConfig(CollaborationProjectConfigurationType configType, const std::wstring& buildingItemId, const std::wstring& configId, int version) = 0;

        /// \brief 析构函数
        virtual ~IDataset();
    };
}
